package jtokyotyrant.jni;

import java.nio.charset.Charset;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.util.HashMap;

import jtokyotyrant.util.StringUtil;

class JniUtil {
	public static final String DEFAULT_CHARSET = "UTF-8";

	public static final Charset CHARSET_JNI_TO_JAVA;
	public static final Charset CHARSET_JAVA_TO_JNI;
	
	public static String SYSPROP_ENCODING_JNI_TO_JAVA = "jtt.encodingJniToJava";
	public static String SYSPROP_ENCODING_JAVA_TO_JNI = "jtt.encodingJavaToJni";
	
	static {
		String charsetName = System.getProperty(SYSPROP_ENCODING_JNI_TO_JAVA);
		if (charsetName != null && Charset.isSupported(charsetName)) {
			CHARSET_JNI_TO_JAVA = Charset.forName(charsetName);
		} else {
			CHARSET_JNI_TO_JAVA = Charset.forName(DEFAULT_CHARSET);
		}

		charsetName = System.getProperty(SYSPROP_ENCODING_JAVA_TO_JNI);
		if (charsetName != null && Charset.isSupported(charsetName)) {
			CHARSET_JAVA_TO_JNI = Charset.forName(charsetName);
		} else {
			CHARSET_JAVA_TO_JNI = Charset.forName(DEFAULT_CHARSET);
		}
	}
	
	private JniUtil() {
	}
	

	public static byte[] strToBytes(String str) {
		return (StringUtil.isEmpty(str) 
			? new byte[0]
			: str.getBytes(CHARSET_JAVA_TO_JNI));
	}
	
	public static String bytesToStr(byte[] bytes) {
		return (bytes == null || bytes.length == 0
			? ""
			: new String(bytes, CHARSET_JNI_TO_JAVA));
	}
	
	public static <K, V> Map<byte[], byte[]> strToBytes(Map<K, V> map) {
		final Map<byte[], byte[]> byteMap = new HashMap<byte[], byte[]>(map.size());
		V value = null;
		byte[] byteKey, byteValue;
		for (K key : map.keySet()) {
			if (key instanceof String) {
				byteKey = strToBytes((String)key);
			} else if (key instanceof byte[]) {
				byteKey = (byte[]) key;
			} else {
				throw new IllegalArgumentException("key type is suppreted String or byte[]");
			}
			value = map.get(key);
			if (value instanceof String) {
				byteValue = strToBytes((String)value);
			} else if (value instanceof byte[]) {
				byteValue = (byte[]) value;
			} else {
				throw new IllegalArgumentException("value type is suppreted String or byte[]");
			}
			byteMap.put(byteKey, byteValue);
		}
		return byteMap;
	}
	
	public static <K, V> Map<String, String> bytesToStr(Map<K, V> map) {
		final Map<String, String> strMap = new HashMap<String, String>(map.size());
		String strValue, strKey;
		V value = null;
		for (K key : map.keySet()) {
			if (key instanceof byte[]) {
				strKey = bytesToStr((byte[]) key);
			} else if (key instanceof String) {
				strKey = (String) key;
			} else {
				throw new IllegalArgumentException("key type is suppreted String or byte[]");
			}
			
			value = map.get(key);
			if (value instanceof byte[]) {
				strValue = bytesToStr((byte[]) value);
			} else if (value instanceof String) {
				strValue = (String) value;
			} else {
				throw new IllegalArgumentException("value type is suppreted String or byte[]");
			}
			strMap.put(strKey, strValue);
		}
		return strMap;
	}


	public static List<String> bytesToStr(List<byte[]> byteList) {
		final List<String> strList = new ArrayList<String>(byteList.size());
		for (byte[] item : byteList) {
			strList.add(bytesToStr(item));
		}
		return strList;
	}

	public static List<byte[]> strToBytes(List<String> strList) {
		final List<byte[]> byteList = new ArrayList<byte[]>(strList.size());
		for (String item : strList) {
			byteList.add(strToBytes(item));
		}
		return byteList;
	}

	static String b2s(byte[] bytes) { return bytesToStr(bytes); }
	static byte[] s2b(String str) { return strToBytes(str); }
	static <K, V> Map<String, String> b2s(Map<K, V> bytes) { return bytesToStr(bytes); }
	static <K, V> Map<byte[], byte[]> s2b(Map<K, V> str) { return strToBytes(str); }
	static List<String> b2s(List<byte[]> bytes) { return bytesToStr(bytes); }
	static List<byte[]> s2b(List<String> str) { return strToBytes(str); }

		
}
